#pragma once
#include <iostream>
#include <assert.h>
#include <string>
#include <typeinfo>

class Any
{
private:
    //  父类
    class holder
    {
    public:
        virtual ~holder() {}
        virtual const std::type_info &type() = 0;
        virtual holder *clone() = 0;
    };
    // 子类
    template <class T>
    class placeholder : public holder
    {
    public:
        placeholder(const T &val) : _val(val) {}
        // 获取子类的数据类型
        virtual const std::type_info &type() { return typeid(T); }
        // 针对当前对象自身，克隆出一个新的子类对象
        virtual holder *clone() { return new placeholder(_val); }

    public:
        T _val;
    };

    holder *_content;

public:
    Any() : _content(nullptr) {}
    template <class T>
    Any(const T &val) : _content(new placeholder<T>(val)) {}
    Any(const Any &other) : _content(other._content ? other._content->clone() : nullptr) {}
    ~Any() { delete _content; }

    // 交换两个Any容器的_content指针
    void swap(Any &other) { std::swap(_content, other._content); }

    // 返回子类对象保存的数据的指针
    template <class T>
    T *get()
    {
        // 获取的数据类型必须和保存的数据类型一致
        assert(typeid(T) == _content->type());
        return &(((placeholder<T> *)_content)->_val);
    }
    // 给子类对象保存的数据赋值
    template <class T>
    Any &operator=(const T &val)
    {
        Any(val).swap(*this);
        return *this;
    }
    // 通过其他的通用容器进行赋值
    Any &operator=(const Any &other)
    {
        Any(other).swap(*this);
        return *this;
    }
};